#pragma once
#include<iostream>
#include <sys/types.h>           
#include <sys/socket.h>
#include <arpa/inet.h>
#include<string.h>
#include<string>
#include"Log.hpp"
enum{
    BindErr=1,
    SockErr,
    ListenErr,
    ConnectErr,
    AcceptErr,
};
const int backlog=10;
class Sock
{
public:
    Sock(){}

    int getfd()
    {
        return _sockfd;
    }

    bool Socket()
    {
        _sockfd=socket(AF_INET,SOCK_STREAM,0);
        if(_sockfd<0)
        {
            lg(Fatal,"socket error:%s,%d",strerror(errno),errno);
            exit(SockErr);
        }
        return true;
    }

    bool Bind(uint16_t port)
    {
        sockaddr_in peer;
        peer.sin_family=AF_INET;
        peer.sin_port=htons(port);
        peer.sin_addr.s_addr=INADDR_ANY;
        int len=sizeof(peer);
        if(bind(_sockfd,(sockaddr*)&peer,len)<0)
        {
            lg(Fatal,"bind error: %s,%d",strerror(errno),errno);
            exit(BindErr);
        }
        return true;
    }

    bool Listen()
    {
        if(listen(_sockfd,backlog)<0)
        {
            lg(Fatal,"listen error: %s,%d",strerror(errno),errno);
            exit(BindErr);
        }
        return true;
    }

    bool Connect(const std::string&ip,uint16_t port)
    {
        sockaddr_in peer;
        bzero(&peer,0);
        peer.sin_family=AF_INET;
        peer.sin_port=htons(port);
        inet_pton(AF_INET,ip.c_str(),&(peer.sin_addr));
        if(connect(_sockfd,(sockaddr*)&peer,sizeof(peer))<0)
        {
            lg(Fatal,"connect error:%s,%d",strerror(errno),errno);
            exit(ConnectErr);
        }
        return true;
    }

    int Accept(std::string&clientip,uint16_t&clientport)
    {
        sockaddr_in peer;
        socklen_t len=sizeof(peer);
        int n=accept(_sockfd,(sockaddr*)&peer,&len);
        if(n<0)
        {
            lg(Fatal,"accept error:%s,%d",strerror(errno),errno);
            exit(AcceptErr);
        }
        char inptr[128];
        inet_ntop(AF_INET,&(peer.sin_addr),inptr,sizeof(inptr));
        clientip=inptr;
        clientport=ntohs(peer.sin_port);
        return n;
    }

    void Close()
    {
        close(_sockfd);
    }
private:
    int _sockfd;
};
